//
// Created by User on 24-10-9.
//

#ifndef GENERAL_MUXER_H
#define GENERAL_MUXER_H

#include "muxer_error.hpp"
#include "media_packet.h"
#include "muxer.h"
#include <string>
#include <vector>
#include <atomic>

namespace utils
{
    class media_packet;
}

extern "C" {
#include <libavutil/rational.h>
struct AVFormatContext;
struct AVStream;
}

namespace interfaces
{
    class packet_provider;
}

namespace muxer
{
    class general_muxer
            : public interfaces::muxer
    {
    public:
        general_muxer(const std::string& path, const std::vector<interfaces::packet_provider*>& providers);

        ~general_muxer();

        bool start_mux();

        void pause_mux();

        bool continue_mux();

        int current_frames() const;

    private:
        void init_muxer(const std::string& path);

        void clean_muxer(error::muxer_error::type _type);

        void write_pkt();

        int min_pts(const std::vector<int>& pts_vec, const std::vector<bool>& marker);

        void write_single_pkt(utils::media_packet& pkt, AVRational input_timebase, AVStream* output_stream);

    private:
        int m_total_frames{};
        std::atomic<int> m_curr_frames{0};
        std::atomic<bool> pause_flag{false};
        std::vector<interfaces::packet_provider*> m_providers{};
        std::vector<AVStream*> m_streams{};
        AVFormatContext* m_fmt_ctx{};

        std::vector<int> pts_vec{};
        AVStream* output_stream{};
        AVRational input_timebase{};
        utils::media_packet pkt{};
        int end_counter{};
        std::vector<bool> marker{};

    };
}
#endif //GENERAL_MUXER_H
